package com.zzy.transaction.future;

import com.zzy.transaction.context.TransactionMeta;
import com.zzy.transaction.exception.TransactionExecuteException;
import com.zzy.transaction.manager.TransactionCoordinator;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicInteger;

@Data
@Slf4j
public class Monitor {

    private volatile boolean error;

    private boolean release;

    private Throwable cause;

    private AtomicInteger completeCount = new AtomicInteger(0);

    // 1:最终状态为成功
    private int status;

    public synchronized boolean isError() {
        return this.error;
    }

    public void setError(boolean error, Throwable cause) {
        int completed = completeCount.incrementAndGet();
        release(error, cause);
        try {
            TransactionMeta transactionMeta = TransactionCoordinator.get();
            CountDownLatch countDownLatch = transactionMeta.getCountDownLatch();
            countDownLatch.countDown();
            // 如果发生异常，这里会被唤醒
            boolean notTimeout = countDownLatch.await(transactionMeta.getTimeout(), transactionMeta.getTimeUnit());
            if (!notTimeout) {
                release(true, new TimeoutException());
            }
            if (this.isError()) {
                release(true, null);
            }
            success(completed);
        } catch (InterruptedException e) {
            release(error, e);
        }
    }

    public synchronized void success(int completed) {
        // 再次判断下，防止timeoutRelease将标志位改变
        if (this.error) {
            throw new TransactionExecuteException("调用方已超时");
        }
        // 表示有已经成功完成的事务
        this.status = 1;
        if (completed == TransactionCoordinator.get().getTaskCount()) {
            TransactionCoordinator.get().finish(true);
        }
    }

    public void release(boolean isError, Throwable cause) {
        TransactionMeta transactionMeta = TransactionCoordinator.get();
        CountDownLatch countDownLatch = transactionMeta.getCountDownLatch();
        synchronized (this) {
            if (this.error) {
                // 释放资源
                throw new TransactionExecuteException("同批次业务执行中发生异常");
            }
            if (isError) {
                this.error = true;
                TransactionCoordinator.get().finish(false);
                if (!release) {
                    // 全部释放
                    for (int i = 0; i < transactionMeta.getTaskCount(); i++) {
                        countDownLatch.countDown();
                    }
                    this.release = true;
                }
                if (cause == null) {
                    throw new TransactionExecuteException("业务执行发生异常");
                } else {
                    this.cause = cause;
                    throw new TransactionExecuteException(cause);
                }
            }
        }
    }


    public boolean timeoutRelease(TransactionMeta transactionMeta,Throwable cause) {
        CountDownLatch countDownLatch = transactionMeta.getCountDownLatch();
        synchronized (this) {
            if (this.error) {
                return false;
            }
            if (this.status != 1) {
                // 只要有成功完成的事务就不能回滚
                this.error = true;
                if (!release) {
                    // 全部释放
                    for (int i = 0; i < transactionMeta.getTaskCount(); i++) {
                        countDownLatch.countDown();
                    }
                    this.release = true;
                }
                this.cause = cause;
                throw new TransactionExecuteException(cause);
            } else {
                return true;
            }
        }
    }
}
